package cn.e2win.biz.security;

import java.io.IOException;
import java.util.Collection;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

import cn.e2win.base.entity.SysUser;


public class DmsSecurityFilter extends AbstractSecurityInterceptor implements Filter {  
	static Log logger = LogFactory.getLog(DmsSecurityFilter.class);
    //与applicationContext-security.xml里的Filter的属性securityMetadataSource对应，  
    //其他的两个组件，已经在AbstractSecurityInterceptor定义  
    private FilterInvocationSecurityMetadataSource securityMetadataSource;
  
    @Override  
    public SecurityMetadataSource obtainSecurityMetadataSource() {  
        return this.securityMetadataSource;  
    }  
  
    public void doFilter(ServletRequest request, ServletResponse response,  
            FilterChain chain) throws IOException, ServletException { 
    	
    	HttpServletRequest req = (HttpServletRequest) request;
    	if (req.getHeader("X-Requested-With") != null && req.getHeader("X-Requested-With").equalsIgnoreCase("XMLHttpRequest")) {
    		request.setCharacterEncoding("utf-8");
    	} else {
    		//request.setCharacterEncoding("gbk");
    		request.setCharacterEncoding("utf-8");
    	}
    	//chain.doFilter(request, response);
    	
    	
        FilterInvocation fi = new FilterInvocation(request, response, chain);  
        invoke(fi);  
        
        
    }
    
    
	private void invoke(FilterInvocation fi) throws IOException, ServletException {  
        // object为FilterInvocation对象  
                  //super.beforeInvocation(fi);源码  
        //1.获取请求资源的权限  
        //执行Collection<ConfigAttribute> attributes = SecurityMetadataSource.getAttributes(object);  
        //2.是否拥有权限  
        //this.accessDecisionManager.decide(authenticated, object, attributes);  
        InterceptorStatusToken token = super.beforeInvocation(fi);  
        Authentication  authentication =  SecurityContextHolder.getContext().getAuthentication();
        try {
 		    SysUser user = (SysUser)authentication.getPrincipal();
 		  
        } catch (Exception e) {
			throw new AuthenticationCredentialsNotFoundException("not login");
		} finally {  
            super.afterInvocation(token, null);  
        }
        
        Collection<ConfigAttribute> attributes = securityMetadataSource.getAttributes(fi);
		    super.getAccessDecisionManager().decide(authentication, fi, attributes);
        fi.getChain().doFilter(fi.getRequest(), fi.getResponse());  
        
    }  
  
    public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {  
        return securityMetadataSource;  
    }  
  
    public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) {  
        this.securityMetadataSource = securityMetadataSource;  
    }  
      
    public void init(FilterConfig arg0) throws ServletException {  
        // TODO Auto-generated method stub  
    }  
      
    public void destroy() {  
        // TODO Auto-generated method stub  
          
    }  
  
    @Override  
    public Class<? extends Object> getSecureObjectClass() {  
        //下面的MyAccessDecisionManager的supports方面必须放回true,否则会提醒类型错误  
        return FilterInvocation.class;  
    }  
}  
